local Log = require('x_cmp_cn.log')
Log.init_log()

local M = {}
M.jieba = require('x_cmp_cn.jieba'):new()

-- 检查是否为汉字
local function is_chinese_char(char)
  if not char or char == "" then return false end
  local cp = vim.fn.char2nr(char) -- 使用Neovim内置函数获取Unicode码点
  return cp >= 0x4E00 and cp <= 0x9FFF
end

-- 初始化
function M.setup()
	-- 创建用户命令 x_cmp_show_cur_buffer_cn_segmented
	vim.api.nvim_create_user_command("XCmpShowSegs", function()
		M:cmd_show_cur_buffer_cn_segmented()
	end, {})
end

--------------------------------------------------------------------------------
-- blink.cmp 中文分词补全源 - 性能优化版本
-- 优化策略：
-- 1. 缓存机制：避免重复分词，每个buffer缓存分词结果
-- 2. 自动更新：通过autocmd监听文本变化，自动清除缓存
-- 3. 防抖机制：使用200ms防抖，避免频繁更新缓存
-- 4. 异步处理：使用vim.defer_fn异步执行分词，避免UI阻塞

-- 初始化blink.cmp源
-- 返回：新的源对象，包含缓存和防抖计时器
function M:new()
	local o = setmetatable({}, { __index = M })
	o.cache = {} -- 每个buffer的分词结果缓存，key为buffer number，value为分词集合
	o.debounce_timers = {} -- 每个buffer的防抖计时器，避免频繁更新缓存
	return o
end

-- 为指定buffer设置自动命令
-- 当buffer内容变化时，自动清除缓存（带防抖）
-- 参数：bufnr - buffer编号
function M:setup_autocmd(bufnr)
	local group = vim.api.nvim_create_augroup("XcmpCn", { clear = true })
	vim.api.nvim_create_autocmd("TextChanged", {
		buffer = bufnr,
		group = group,
		callback = function()
			-- 取消之前的防抖计时器
			if self.debounce_timers[bufnr] then
				self.debounce_timers[bufnr]:close()
			end
			-- 创建新的防抖计时器，200ms后清除缓存
			self.debounce_timers[bufnr] = vim.loop.new_timer()
			self.debounce_timers[bufnr]:start(200, 0, function()
				self:clear_cache(bufnr)
			end)
		end,
	})
end

-- 清除指定buffer的缓存
-- 参数：bufnr - buffer编号
function M:clear_cache(bufnr)
	self.cache[bufnr] = nil
end

-- 异步更新指定buffer的缓存
-- 使用vim.defer_fn实现异步分词，避免阻塞UI
-- 参数：bufnr - buffer编号
function M:update_cache(bufnr)
	-- 使用vim.defer_fn异步执行，0延迟表示立即执行但非阻塞
	vim.defer_fn(function()
		-- 获取buffer全部内容
		local buffer_content = table.concat(vim.api.nvim_buf_get_lines(bufnr, 0, -1, false), "\n")
		-- 执行分词（这是CPU密集型操作）
		local words = M.jieba:cut(buffer_content)
		
		-- 在主线程更新缓存（vim.schedule确保线程安全）
		vim.schedule(function()
			-- 将分词结果以有序列表的形式存入缓存
			local word_list = {}
			for w in string.gmatch(words, "%S+") do
				table.insert(word_list, w)
			end
			self.cache[bufnr] = word_list
		end)
	end, 0)
end

-- 辅助函数：创建并插入补全项
-- 参数：
--   items - 补全项列表
--   seen - 用于去重的哈希表
--   label - 补全项的显示文本
--   kw - cmp的关键字
--   ctx - cmp的上下文
--   is_w1 - 是否为w1（w1需要消掉左侧1个字符）
local function insert_item(items, seen, label, kw, ctx, is_w1)
	if not seen[label] then
		seen[label] = true
		local left_occupy = (is_w1) and 3 or 0 -- w1需要消掉左侧1个字符，3 byte
		table.insert(items, {
			label = label,
			kind = require('blink.cmp.types').CompletionItemKind.Text,
			filterText = kw .. "xue" .. label,
			textEdit = {
				newText = label,
				range = {
					start = { line = ctx.cursor[1]-1, character = ctx.cursor[2]-left_occupy },
					['end'] = { line = ctx.cursor[1]-1, character = ctx.cursor[2]-left_occupy },
				},
			},
		})
	end
end

-- 获取补全项（blink.cmp回调函数）
-- 优化流程：
-- 1. 检查缓存是否存在，不存在则异步创建
-- 2. 缓存未就绪时返回空结果，避免阻塞
-- 3. 从缓存中快速筛选包含输入字符的词
-- 参数：
--   ctx - blink.cmp上下文，包含光标位置、输入内容等
--   callback - 补全结果回调函数
function M:get_completions(ctx, callback)
	local ft = vim.bo.filetype;
	if ft ~= 'text' and ft ~= 'markdown' then 
		callback({items = {}})
	end

	--Log:write_log(vim.inspect(ctx))
	local cur_buf = vim.api.nvim_get_current_buf()
	
	-- 首次为buffer获取补全时，初始化缓存和自动命令
	if not self.cache[cur_buf] then
		self:update_cache(cur_buf)  -- 异步更新缓存
		self:setup_autocmd(cur_buf) -- 设置自动命令监听
	end
	
	local kw = ctx.get_keyword()
	--Log:write_log(kw)
	local segs = self.cache[cur_buf]
	
	-- 缓存未就绪时返回空结果（避免阻塞用户输入）
	if not segs then
		callback({ items = {} })
		return
	end

	-- 获取输入的最后一个字符（用于匹配）
	local ctx_col = ctx.cursor[2] -- byte 列数，0-based
	local last_index = vim.fn.charidx(ctx.line, ctx_col) -- 光标位置字符索引
	local last_char = vim.fn.strcharpart(ctx.line, last_index-1, 1) -- 减1获取左侧字符
	
	if last_char == "" then
		--Log:write_log("last_char = empty")
		return
	else
		--Log:write_log("last_char = " .. last_char)
	end

	-- 非中文字符不提供补全
	if not is_chinese_char(last_char) then
		return
	end

	-- 从缓存中筛选包含输入字符的词，构建补全项
	local items = {}
	local seen = {}
	for i = 1, #segs, 1 do
		local w1 = segs[i]

		-- 检查w1是否以last_char开头，且不以last_char结尾
		if string.find(w1, "^" .. last_char) and not string.find(w1, last_char .. "$") then
			insert_item(items, seen, w1, kw, ctx, true)
			local w2 = (i + 1 <= #segs) and segs[i + 1] or nil
			if w2 then
				insert_item(items, seen, w1 .. w2, kw, ctx, true)
			end
			local w3 = (i+2 <= #segs) and segs[i+2] or nil
			if w3 then
				insert_item(items, seen, w1 .. w2 .. w3, kw, ctx, true)
			end	
		end

		-- 检查w1是否以last_char结尾
		if string.find(w1, last_char .. "$") then
			local w2 = (i + 1 <= #segs) and segs[i + 1] or nil
			if w2 then
				insert_item(items, seen, w2, kw, ctx, false)
				local w3 = (i + 2 <= #segs) and segs[i + 2] or nil
				if w3 then
					insert_item(items, seen, w2 .. w3, kw, ctx, false)
				end
			end
		end
	end

	-- 返回补全结果
	callback({
		items = items,
		is_incomplete_backward = true,
		is_incomplete_forward = true,
	})
end

--------------------------------------------------------------------------------
return M
